#include "pch.h"
#include "treeview.h"
#include <common/winapi.h>

INT treeview_itemcount(JOUI::info_tree_nodeitem* item)
{
    INT pCount = 0;
    while (item)
    {
        pCount++;
        if (item->fExpand)
        {
            pCount += treeview_itemcount(item->pChildFirst);
        }
        item = item->pNext;
    }
    return pCount;
}
JOUI::info_tree_nodeitem* treeview_getitembyindex(JOUI::info_tree_nodeitem* item, INT index, INT* childIndex)
{
    if (index <= 0)
    {
        return 0;
    }
    if (*childIndex == 0)
    {
        *childIndex = 1;
    }
    while (item)
    {
        if (*childIndex == index)
        {
            return item;
        }
        (*childIndex)++;
        if (item->fExpand)
        {
            auto tmp = treeview_getitembyindex(item->pChildFirst, index, childIndex);
            if (tmp)
            {
                return tmp;
            }
        }
        item = item->pNext;
    }
    return NULL;
}
void treeview_deleteitemlink(JOUI::info_tree_nodeitem* nodeitem, JOUI::info_tree_nodeitem* item)
{
    if (item)
    {
        JOUI::info_tree_nodeitem* next = item->pNext;
        JOUI::info_tree_nodeitem* prev = item->pPrev;
        item->pNext = NULL;
        item->pPrev = NULL;
        if (next)
        {
            next->pPrev = prev;
        }
        if (prev)
        {
            prev->pNext = next;
        }
        JOUI::info_tree_nodeitem* parent = item->pParent;
        item->pParent = NULL;
        if (!prev)
        {
            if (parent)
            {
                parent->pChildFirst = next;
            }
            else if (nodeitem == item)
            {
                nodeitem = next;
            }
        }
    }
}
void treeview_freeitemID(JOUI::info_tree_nodeitem* nodeitem, JOUI::info_tree_nodeitem* item)
{
    JOUI::info_tree_nodeitem* child = item->pChildFirst;

    while (child)
    {
        JOUI::info_tree_nodeitem* tmp = child->pNext;
        treeview_deleteitemlink(nodeitem, child);
        treeview_freeitemID(nodeitem, child);
        if (child->pwzText)
            LocalFree((HLOCAL)child->pwzText);
        if (child->nImageIndex)
        {
            delete child->nImageIndex;
            child->nImageIndex = nullptr;
        }
        delete child;
        child = tmp;
    }
    item->nCountChild = 0;
}
void treeview_freeitem(JOUI::info_tree_nodeitem* nodeitem, JOUI::info_tree_nodeitem* item, BOOL child, BOOL dellink, BOOL destroy)
{
    if (item)
    {
        if (dellink)
        {
            if (item->pParent)
            {
                item->pParent->nCountChild = item->pParent->nCountChild - 1;
                if (item->pParent->nCountChild < 0)
                    item->pParent->nCountChild = 0;
            }
            treeview_deleteitemlink(nodeitem, item);

        }
        if (child)
            treeview_freeitemID(nodeitem, item);

    }
}
LPVOID JOUI::UITreeView::InsertItem(LPVOID itemParent, LPVOID itemInsertAfter, INT nID, LPCWSTR pwzText, LPARAM lParam,
    UIImage* nImageIndex, BOOL fExpand, BOOL fUpdate, UIColor color, INT select)
{
    BOOL bShowAllwasy = ((m_data.dwStyle & eos_elvs_allowmultiple) == eos_elvs_allowmultiple);
    info_tree_nodeitem* tvitem = new info_tree_nodeitem();
    if (tvitem && inititem(tvitem, (info_tree_nodeitem*)itemParent, (info_tree_nodeitem*)itemInsertAfter))
    {
        if (pwzText)
            tvitem->pwzText = StrDupW(pwzText);
        tvitem->lParam = lParam;
        tvitem->nImageIndex = nImageIndex;
        tvitem->fExpand = fExpand;
        tvitem->color = color;
        tvitem->nID = nID;
        if (bShowAllwasy)
            tvitem->select = select;
        if (nImageIndex)
            nImageIndex->GetSize(tvitem->imgWidth, tvitem->imgHeight);

        updateitem();
        if (fUpdate)
        {
            INT count = treeview_itemcount(s_data.nodeitem);
            SetItemCount(count, LVSICF_NOSCROLL);
            generatelist(TRUE);
        }
    }
    return tvitem;
}

void JOUI::UITreeView::InsertItem(LPVOID itemParent, LPVOID itemInsertAfter, info_tree_nodeitem* item)
{
    BOOL bShowAllwasy = ((m_data.dwStyle & eos_elvs_allowmultiple) == eos_elvs_allowmultiple);
    if (item && inititem(item, (info_tree_nodeitem*)itemParent, (info_tree_nodeitem*)itemInsertAfter))
    {
        if (item->nImageIndex)
            item->nImageIndex->GetSize(item->imgWidth, item->imgHeight);

        updateitem();
    }
}

void JOUI::UITreeView::SetItem(INT Index, LPCWSTR pwzText, LPARAM lParam, INT nID, UIImage* nImageIndex, UIColor color, INT select, BOOL fUpdate)
{
    INT tmp = 0;
    auto item = treeview_getitembyindex(s_data.nodeitem, Index, &tmp);
    if (item)
    {
        if (pwzText)
        {
            LocalFree((HLOCAL)item->pwzText);
            item->pwzText = StrDupW(pwzText);
        }
        if (lParam)
            item->lParam = lParam;
        if (nImageIndex)
        {
            delete item->nImageIndex;
            item->nImageIndex = nImageIndex;
            item->nImageIndex->GetSize(item->imgWidth, item->imgHeight);
        }
        if (!color.empty())
            item->color = color;
        if (select != -1)
            item->select = select;
        if (nID != 0)
            item->nID = nID;
        if (fUpdate)
        {
            updateitem();
            Redraw();
        }
    }
}

void JOUI::UITreeView::Update()
{
    INT count = treeview_itemcount(s_data.nodeitem);
	SetItemCount(count, LVSICF_NOSCROLL);
    generatelist(TRUE);
	Redraw();
}
void JOUI::UITreeView::Expand(INT Index, BOOL fExpand)
{
    INT tmp = 0;
    auto item = treeview_getitembyindex(s_data.nodeitem, Index, &tmp);
    if (item)
        fiExpand(item, fExpand);
}
BOOL JOUI::UITreeView::IsExpand(INT Index)
{
    INT tmp = 0;
    auto item = treeview_getitembyindex(s_data.nodeitem, Index, &tmp);
    if (item)
        return item->fExpand;
    return FALSE;
}
void JOUI::UITreeView::GetIdItem(INT nID, info_tree_nodeitem*& item)
{
    INT tmp = 0;
    item = treeview_getitembyindex(s_data.nodeitem, nID, &tmp);
}
void JOUI::UITreeView::GetIndexItem(INT Index, info_tree_nodeitem*& item)
{
    INT tmp = 0;
    item = treeview_getitembyindex(s_data.nodeitem, Index, &tmp);
}
INT JOUI::UITreeView::DeleteItem(INT Index, bool draw)
{
    INT count = 0, tmp = 0;
    auto item = treeview_getitembyindex(s_data.nodeitem, Index, &tmp);
    if (item)
    {
        treeview_freeitem(s_data.nodeitem, item, TRUE, TRUE, TRUE);
        if (Index == s_data.setselect)
            s_data.setselect = -1;
        if (draw)
        {
            count = treeview_itemcount(s_data.nodeitem);
            SetItemCount(count, LVSICF_NOSCROLL);
            generatelist(TRUE);
            Redraw();
        }
    }
    return count;
}
void JOUI::UITreeView::DeleteAllItem(INT Index, bool draw)
{
    info_tree_nodeitem* item = nullptr; INT tmpindex = 0, tmp = 0;
    if (Index == 0)
    {
        item = s_data.nodeitem;
        while (item)
        {
            info_tree_nodeitem* next = item->pNext;
            treeview_freeitem(s_data.nodeitem, item, TRUE, FALSE, FALSE);

            treeview_deleteitemlink(s_data.nodeitem, item);
            if (item->pwzText)
                LocalFree((HLOCAL)item->pwzText);
            if (item->nImageIndex)
                delete item->nImageIndex;
            delete item;
            item = next;

        }
        s_data.setselect = -1;
    }
    else
    {
        item = treeview_getitembyindex(s_data.nodeitem, Index, &tmp);
        if (item)
        {
            treeview_freeitemID(s_data.nodeitem, item);


            if (Index == s_data.setselect)
                s_data.setselect = -1;
        }
        tmpindex = MAKELONG(LVSICF_NOSCROLL, GetHotItem());
    }
    if (draw)
    {
        INT count = treeview_itemcount(s_data.nodeitem);
        SetItemCount(count, tmpindex);
        generatelist(TRUE);
        Redraw();
    }
}
INT treeview_getvisiblecount(JOUI::info_tree_nodeitem* item, BOOL expand)
{
    INT count = 0;
    while (item)
    {
        count++;
        if (!expand || item->fExpand)
        {
            count += treeview_getvisiblecount(item->pChildFirst, expand);
        }
        item = item->pNext;
    }
    return count;
}
INT JOUI::UITreeView::GetItemCount(INT Index)
{
    if (Index != 0)
    {
        INT count = 0, tmp = 0;
        auto item = treeview_getitembyindex(s_data.nodeitem, Index, &tmp);
        if (item)
        {
            while (item)
            {
                if (item->nCountChild)
                {
                    return item->nCountChild;
                }
                item = item->pNext;
            }
        }
        return 0;
    }
    else
        return treeview_getvisiblecount(s_data.nodeitem, FALSE);
}
INT JOUI::UITreeView::GetItemId(INT Index)
{
    INT tmp = 0;
    auto item = treeview_getitembyindex(s_data.nodeitem, Index, &tmp);
    if (item)
        return item->nID;
    return 0;
}
void JOUI::UITreeView::SetCrSelect(UIColor cr)
{
    s_data.select = cr;
}
void JOUI::UITreeView::SetCrWaddAndsub(UIColor cr)
{
    s_data.color_waddandsub = cr;
}
void JOUI::UITreeView::SetCrCable(UIColor cr)
{
    s_data.color_cable = cr;
}
void treeview_setselect(JOUI::info_tree_nodeitem* parent, JOUI::info_tree_nodeitem* item, INT select)
{
    if (!item) return;
    if (item->pParent == parent)
    {
        item->select = select;
    }
    if (item->fExpand || item->pChildFirst)
    {
        treeview_setselect(parent, item->pChildFirst, select);
    }
    if (item->pNext)
    {
        treeview_setselect(parent, item->pNext, select);
    }
}

LRESULT JOUI::UITreeView::OnPsProc(HWND hWnd, INT uMsg, WPARAM wParam, LPARAM lParam)
{
	if (uMsg == WM_SIZE)
	{
	}
	else if (uMsg == WM_DESTROY)
	{
        auto pItem = s_data.nodeitem;
        while (pItem)
        {
            info_tree_nodeitem* next = pItem->pNext;
            treeview_freeitem(pItem, pItem, TRUE, FALSE, FALSE);
            treeview_deleteitemlink(pItem, pItem);
            if (pItem->pwzText)
                LocalFree((HLOCAL)pItem->pwzText);
            if (pItem->nImageIndex)
            {
                delete pItem->nImageIndex;
                pItem->nImageIndex = nullptr;
            }
            delete pItem;

            pItem = next;
        }
		if (!s_data.isData)
		{
			delete s_data.itemList;
		}
		delete s_data.hBrush;
	}
    else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN)
    {
        INT hitType = 0;
        BOOL bShowAllwasy = ((m_data.dwStyle & eos_elvs_allowmultiple) == eos_elvs_allowmultiple);
        auto pItem = hittest({ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }, hitType);
        if (pItem)
        {
            if (hitType == 1)
            {
                s_data.setselect = pItem->nID;
                DispatchNotify(WMM_TVN_SELECT, 0, pItem->nID);
                Redraw();
            }
            if (hitType == 64)
            {
                fiExpand(pItem, !pItem->fExpand);
                s_data.expand = TRUE;
                return TRUE;
            }
            else if (bShowAllwasy && hitType == 2)
            {
                if (pItem->select == 0 || pItem->select == -1)
                {
                    pItem->select = 1;
                    if (pItem->nCountChild != 0)
                        treeview_setselect(pItem, s_data.nodeitem, 1);
                }
                else
                {
                    pItem->select = 0;
                    if (pItem->nCountChild != 0)
                        treeview_setselect(pItem, s_data.nodeitem, 0);
                }
                //s_data.setselect = pItem->nID;

                DispatchNotify(WMM_TVN_SELECTALL, pItem->select, pItem->nID);
                Redraw();
                return TRUE;
            }
        }
    }
	return S_OK;
}

BOOL JOUI::UITreeView::OnPsCustomDraw(INT iItem, ps_customdraw ps)
{
    generatelist(FALSE);

	INT index = iItem - p_data.index_start + 1;
	BOOL bShowAllwasy = ((m_data.dwStyle & eos_elvs_allowmultiple) == eos_elvs_allowmultiple);

    info_tree_nodeitem* pItemInfo = s_data.itemList->at(index);
    if (pItemInfo)
    {
        RECT rect{};
        rect.left = ps.rcPaint.left + fScale(5) + pItemInfo->nDepth * s_data.indent;
        rect.right = rect.left + fScale(10);
        rect.top = (ps.rcPaint.bottom + ps.rcPaint.top - fScale(10)) / 2;
        rect.bottom = (ps.rcPaint.bottom + ps.rcPaint.top + fScale(10)) / 2;
        bool reDraw = false;

        if (ps.dwState & state_select)
        {
            s_data.hBrush->SetColor(s_data.Color[1]);
            reDraw = true;
        }
        else if (ps.dwState & state_hover)
        {
            s_data.hBrush->SetColor(s_data.Color[0]);
            reDraw = true;
        }
        if (reDraw)
            ps.hCanvas->FillRect(s_data.hBrush, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
        if (pItemInfo->pChildFirst)
        {

            if (FLAGS_CHECK(m_data.dwStyle, eos_tree_showaddandsub))
            {
                s_data.hBrush->SetColor(s_data.color_waddandsub);
                /*
                ps.hCanvas->DrawLine(s_data.hBrush, rect.left - 1, rect.top, rect.left - 1, rect.bottom, 1.0f);
                ps.hCanvas->DrawLine(s_data.hBrush, rect.left, rect.top, rect.right - 1, rect.top, 1.0f);
                ps.hCanvas->DrawLine(s_data.hBrush, rect.right - 1, rect.top, rect.right - 1, rect.bottom, 1.0f);
                ps.hCanvas->DrawLine(s_data.hBrush, rect.left, rect.bottom, rect.right - 1, rect.bottom, 1.0f);

                ps.hCanvas->DrawLine(s_data.hBrush, rect.left + 1, (rect.top + rect.bottom) / 2, rect.right - 3 / g_drawing_default_dpi, (rect.top + rect.bottom) / 2, 1.0f);
                if (!pItemInfo->fExpand)
                {
                    ps.hCanvas->DrawLine(s_data.hBrush, (rect.left + rect.right) / 2 - 1, rect.top + fScale(2), (rect.left + rect.right) / 2 - 1, rect.bottom - fScale(2), 1.0f);
                }*/

                if (pItemInfo->fExpand)
                {
                    ps.hCanvas->FillPoly(s_data.hBrush, rect.left, rect.top + 1, rect.right - 2, rect.top + fScale(8), 3, 90.f);
                }
                else
                {
                    ps.hCanvas->FillPoly(s_data.hBrush, rect.left + 1, rect.top + 1, rect.right - 3 / g_drawing_default_dpi, rect.top + fScale(9), 3, 0.f);
                }
            }
        }
        if (FLAGS_CHECK(m_data.dwStyle, eos_tree_showcable))
        {
            rect.top = ps.rcPaint.top;
            rect.bottom = ps.rcPaint.bottom;
            s_data.hBrush->SetColor(s_data.color_cable);
            if (pItemInfo->pChildFirst)
            {
                if (pItemInfo->pNext)
                {
                    ps.hCanvas->DrawLine(s_data.hBrush,
                        (rect.left + rect.right) / 2 - 1 * g_drawing_default_dpi,
                        (ps.rcPaint.bottom + ps.rcPaint.top + fScale(10)) / 2,
                        (rect.left + rect.right) / 2 - 1 * g_drawing_default_dpi,
                        rect.bottom,
                        1.0f, D2D1_DASH_STYLE_DOT);
                }
                if (pItemInfo->pParent || pItemInfo->pPrev)
                {
                    ps.hCanvas->DrawLine(s_data.hBrush,
                        (rect.left + rect.right) / 2 - 1 * g_drawing_default_dpi,
                        rect.top,
                        (rect.left + rect.right) / 2 - 1 * g_drawing_default_dpi,
                        (ps.rcPaint.bottom + ps.rcPaint.top - fScale(10)) / 2,
                        1.0f, D2D1_DASH_STYLE_DOT);
                }
            }
            if (!pItemInfo->pChildFirst && !pItemInfo->pParent)
            {
                INT top = rect.top + (rect.bottom - rect.top) / 2;
                INT bottom = rect.top + (rect.bottom - rect.top) / 2;
                ps.hCanvas->DrawLine(s_data.hBrush,
                    rect.left + fScale(5),
                    top,
                    rect.left + fScale(12),
                    bottom,
                    1.0f, D2D1_DASH_STYLE_DOT);
                if (pItemInfo->pPrev)
                {
                    top = rect.top;
                }
                if (pItemInfo->pNext)
                {
                    bottom = rect.bottom;
                }
                ps.hCanvas->DrawLine(s_data.hBrush,
                    rect.left + fScale(4),
                    top,
                    rect.left + fScale(4),
                    bottom,
                    1.0f, D2D1_DASH_STYLE_DOT);
            }
            info_tree_nodeitem* parent = pItemInfo->pParent;
            info_tree_nodeitem* tmp = pItemInfo;
            while (parent && tmp)
            {
                if (tmp->pParent)
                {
                    if (tmp->pParent->pNext)
                    {
                        INT left = ps.rcPaint.left + fScale(9) + tmp->pParent->nDepth * s_data.indent;
                        ps.hCanvas->DrawLine(s_data.hBrush,
                            left,
                            rect.top,
                            left,
                            rect.bottom,
                            1.0f, D2D1_DASH_STYLE_DOT);
                    }
                }
                if (!tmp->nCountChild)
                {
                    INT top = rect.top + (rect.bottom - rect.top) / 2;
                    INT bottom = rect.top + (rect.bottom - rect.top) / 2;
                    ps.hCanvas->DrawLine(s_data.hBrush,
                        rect.left + fScale(5),
                        top,
                        rect.left + fScale(12),
                        top,
                        1.0f, D2D1_DASH_STYLE_DOT);
                    if (pItemInfo->pNext)
                    {
                        top = rect.bottom;
                    }
                    ps.hCanvas->DrawLine(s_data.hBrush,
                        rect.left + fScale(4),
                        rect.top,
                        rect.left + fScale(4),
                        top,
                        1.0f, D2D1_DASH_STYLE_DOT);
                }
                tmp = tmp->pParent;
                parent = tmp->pParent;
                while (parent && tmp)
                {
                    if (tmp->pParent)
                    {
                        if (tmp->pParent->pNext)
                        {
                            INT left = ps.rcPaint.left + fScale(9) + tmp->pParent->nDepth * s_data.indent;
                            ps.hCanvas->DrawLine(s_data.hBrush,
                                left,
                                rect.top,
                                left,
                                rect.bottom,
                                1.0f, D2D1_DASH_STYLE_DOT);
                        }
                    }
                    if (!tmp->nCountChild)
                    {
                        INT top = rect.top + (rect.bottom - rect.top) / 2;
                        INT bottom = rect.top + (rect.bottom - rect.top) / 2;
                        ps.hCanvas->DrawLine(s_data.hBrush,
                            rect.left + fScale(5),
                            top,
                            rect.left + fScale(12),
                            top,
                            1.0f, D2D1_DASH_STYLE_DOT);
                        if (pItemInfo->pNext)
                        {
                            top = rect.bottom;
                        }
                        ps.hCanvas->DrawLine(s_data.hBrush,
                            rect.left + fScale(4),
                            rect.top,
                            rect.left + fScale(4),
                            top,
                            1.0f, D2D1_DASH_STYLE_DOT);
                    }
                    tmp = tmp->pParent;
                    parent = tmp->pParent;
                }
            }
           
        }
        INT CHECKRC = 0;
        if (bShowAllwasy)
        {
            RECT rcObject{ 0,0,16,16 };
            rcObject.right = fScale(rcObject.right - rcObject.left);
            rcObject.bottom = fScale(rcObject.bottom - rcObject.top);
            rect.left = rect.right;
            rect.right = rect.left + fScale(5);
            CHECKRC = rcObject.right;
            p_data.cr_select->SetColor(s_data.select);
            ExRectF ret = ExRectF(rect.left + fScale(5), ps.rcPaint.top + (ps.rcPaint.bottom - ps.rcPaint.top - rcObject.bottom) / 2, rcObject.right, rcObject.bottom, TRUE);
            if (pItemInfo->select == 1)
            {
                ps.hCanvas->FillRoundRect(p_data.cr_select, ret.left, ret.top, ret.right, ret.bottom, 2);
                p_data.cr_select->SetColor(UIColor(255, 255, 255, 255));
                ps.hCanvas->DrawLine(p_data.cr_select, ret.left + p_data.pots[2].x, ret.top + p_data.pots[2].y, ret.left + p_data.pots[3].x, ret.top + p_data.pots[3].y, 3, 0, TRUE);
                ps.hCanvas->DrawLine(p_data.cr_select, ret.left + p_data.pots[4].x, ret.top + p_data.pots[4].y, ret.left + p_data.pots[3].x, ret.top + p_data.pots[3].y, 3, 0, TRUE);
            }
            else
                ps.hCanvas->DrawRoundRect(p_data.cr_select, ret.left, ret.top, ret.right, ret.bottom, 2, 1.f);
          
        }
        if (pItemInfo->nImageIndex)
        {
            rect.left = rect.right + CHECKRC;
            rect.right = rect.left + pItemInfo->imgWidth + fScale(5);

            INT nWidth = rect.right - rect.left;
            INT nHeight = rect.bottom - rect.top;
            ps.hCanvas->DrawImage(pItemInfo->nImageIndex, rect.left + (nWidth - pItemInfo->imgWidth) / 2, rect.top + (nHeight - pItemInfo->imgHeight) / 2, 255);
        }
        else
        {
            rect.left = rect.right + CHECKRC;
            rect.right = rect.left + fScale(5);
        }
        UIColor color;
        GetColor(color_text_normal, color);
        if (!pItemInfo->color.empty())
        {
            color = pItemInfo->color;
        }
        ps.hCanvas->DrawTextByColor(ps.hFont, pItemInfo->pwzText, -1, ps.dwTextFormat, rect.right, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom, color);

    }
    return FALSE;
}
JOUI::info_tree_nodeitem* treeview_getlastitem(JOUI::info_tree_nodeitem* item)
{
    JOUI::info_tree_nodeitem* last = item;
    while (item)
    {
        last = item;
        item = item->pNext;
    }
    return last;
}
BOOL JOUI::UITreeView::inititem(info_tree_nodeitem* item, info_tree_nodeitem* parent, info_tree_nodeitem* insertAfter)
{
    info_tree_nodeitem* next = NULL;
    info_tree_nodeitem* prev = NULL;
    if (!item)
    {
        return FALSE;
    }
    if (!insertAfter)
    {
        if (parent)
        {
            prev = treeview_getlastitem(parent->pChildFirst);
        }
        else
        {
            prev = treeview_getlastitem(s_data.nodeitem);
        }
        if (prev)
        {
            next = prev->pNext;
        }
        else if (parent)
        {
            next = parent->pChildFirst;
            parent->pChildFirst = item;
        }
        else
        {
            next = s_data.nodeitem;
            s_data.nodeitem = item;
        }
    }
    else
    {
        if (insertAfter->pParent != parent)
        {
            return FALSE;
        }
        prev = insertAfter;
        next = insertAfter->pNext;
    }
    item->pPrev = prev;
    if (prev)
    {
        prev->pNext = item;
    }
    item->pNext = next;
    if (next)
    {
        next->pPrev = item;
    }
    if (parent)
    {
        item->nDepth = parent->nDepth + 1;
    }
    else
    {
        item->nDepth = 0;
    }
    info_tree_nodeitem* origin = item->pParent;
    item->pParent = parent;
    INT nCountChild = item->nCountChild + 1;
    while (parent)
    {
        parent->nCountChild += nCountChild;
        parent = parent->pParent;
    }
    while (origin)
    {
        origin->nCountChild -= nCountChild;
        origin = origin->pParent;
    }
    return TRUE;
}

LPVOID treeview_getnextvisibleitem(LPVOID item)
{
    auto root = (JOUI::info_tree_nodeitem*)item;
    JOUI::info_tree_nodeitem* ret = NULL;
    if (root)
    {
        if (root->fExpand)
        {
            ret = root->pChildFirst;
        }
        if (!ret)
        {
            ret = root->pNext;
            JOUI::info_tree_nodeitem* next = root;
            while (!ret)
            {
                next = next->pParent;
                if (!next)
                {
                    break;
                }
                if (next->fExpand)
                {
                    ret = next->pNext;
                }
            }
        }
    }
    return ret;
}
BOOL JOUI::UITreeView::generatelist(BOOL bForce)
{
    if (s_data.indexstart != p_data.index_start || s_data.indexend != p_data.index_end || bForce)
    {
        INT len = p_data.index_end - p_data.index_start;
        if (len)
        {
            len++;
            s_data.itemList->resize(len + 1);
        }
        else
        {
            s_data.itemList->resize(0);
        }
        INT tmp = 0;
        auto item = treeview_getitembyindex(s_data.nodeitem, p_data.index_start, &tmp);
        if (!item)
        {
            return FALSE;
        }
        INT i = 0;
        while (TRUE)
        {
            ++i;
            if (i + 1 > len || !item)
            {
                break;
            }
            s_data.itemList->at(i - 1) = item;
            item = (info_tree_nodeitem*)treeview_getnextvisibleitem(item);
        }
        s_data.indexstart = p_data.index_start;
        s_data.indexend = p_data.index_end;
        return TRUE;
    }
    return FALSE;
}

void JOUI::UITreeView::updateitem()
{
    INT width = 0;
    calcitemmaxwidth(s_data.nodeitem, width);
    if (width > p_data.width_item)
        p_data.width_item = width;
}

void JOUI::UITreeView::calcitemmaxwidth(info_tree_nodeitem* item, INT& pWidth)
{
    while (item)
    {
        if (item->fExpand && item->pChildFirst)
        {
            calcitemmaxwidth(item->pChildFirst, pWidth);
            item = item->pNext;
        }
        else
        {
            FLOAT width = 0;
            if (UICanvas::CalcTextSize((UIFont*)GetFont(), item->pwzText, -1, 32, 0, 0, &width, NULL) == S_OK)
            {
                if (item->nImageIndex)
                {
                    width += item->nDepth * s_data.indent + item->imgWidth + fScale(35);
                }
                else
                {
                    width += item->nDepth * s_data.indent + fScale(35);
                }
                if (FLAGS_CHECK(m_data.dwStyle, 64))
                {

                    width += fScale(30);
                }
                if (width > pWidth)
                {
                    pWidth = width;
                }
            }
            item = item->pNext;
        }
    }
}
JOUI::info_tree_nodeitem* JOUI::UITreeView::hittest(POINT pt, INT& pType)
{
    info_tree_nodeitem* pItem = NULL;
    size_t cur = p_data.index_mouse - p_data.index_start;

    pType = 1;
    if (cur >= 0 && cur <= s_data.itemList->size())
    {
        pItem = s_data.itemList->at(cur);
        if (pItem)
        {
            RECT rect = { 0 };
            GetItemRect(p_data.index_mouse, rect);
            pt.x -= rect.left;
            pt.y -= rect.top;
            RECT tmp = { 0 };
            tmp.left = rect.left;
            tmp.right = rect.left + pItem->nDepth * s_data.indent + fScale(5);
            tmp.top = rect.top;
            tmp.bottom = rect.bottom;
            if (PtInRect(&tmp, pt))
            {
                pType = 8;
            }
            else
            {
                tmp.left = pItem->nDepth * s_data.indent;
                tmp.right = tmp.left + fScale(16);
                tmp.top = 0;
                tmp.bottom = rect.bottom - rect.top;
                if (pItem->pChildFirst)
                {
                    if (PtInRect(&tmp, pt))
                    {
                        pType = 64;
                    }
                }
                BOOL bShowAllwasy = ((m_data.dwStyle & eos_elvs_allowmultiple) == eos_elvs_allowmultiple);
                if (bShowAllwasy)
                {
                    tmp.left = fScale(16) + pItem->nDepth * s_data.indent;
                    tmp.right = tmp.left + fScale(20);
                    tmp.top = 0;
                    tmp.bottom = rect.bottom - rect.top;
                    if (PtInRect(&tmp, pt))
                    {
                        pType = 2;
                    }
                }

            }
        }
    }

    return pItem;
}
void JOUI::UITreeView::OnCreate()
{
	s_data.hBrush = new UIBrush();
	s_data.itemList = new std::vector<info_tree_nodeitem*>();
    s_data.indent = fScale(20);
    s_data.setselect = -1;
    s_data.color_waddandsub = UIColor(23, 23, 23, 255);
    s_data.color_cable = UIColor(23, 23, 23, 255);
    m_data.dwStyle |= eos_elvs_showcheck;
}

bool JOUI::UITreeView::IndexCheck(INT index)
{
	if (index < (INT)s_data.itemList->size() && index >= 0)
		return true;
	return false;
}
void JOUI::UITreeView::fiExpand(info_tree_nodeitem* item, BOOL fExpand)
{
    if (item->fExpand != fExpand)
    {
        if (!DispatchNotify(WMM_TVN_ITEMEXPANDING, fExpand, item->nID))
        {
            item->fExpand = fExpand;
            DispatchNotify(WMM_TVN_ITEMEXPANDED, fExpand, item->nID);
            INT count = treeview_itemcount(s_data.nodeitem);
            generatelist(TRUE);
            updateitem();
            SetItemCount(count, LVSICF_NOSCROLL);
        }
    }
}